#import "RNCompletedCheckboxCell.h"
#import "NSBezierPath+MCAdditions.h"
#import "NSShadow+MCAdditions.h"

static NSGradient *offGradient, *offGradientPressed, *onGradient, *onGradientPressed;
static NSColor *offBorderColor, *onBorderColor, *checkColor;
static NSShadow *dropShadow, *innerShadow1, *innerShadow2;

@interface RNCompletedCheckboxCell (RNCompletedCheckboxCellPrivateMethods)
-(void)cacheCheckPath_;
-(void)cacheCheckBox_;
-(void)initializeCell_;
@end

@implementation RNCompletedCheckboxCell

@synthesize checkPath = checkPath_;
@synthesize checkBox = checkBox_;

+(void)initialize {
    offGradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedWhite:0.95f alpha:1.0f] endingColor:[NSColor colorWithCalibratedWhite:1.0f alpha:1.0f]];
    offGradientPressed = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedWhite:0.6f alpha:1.0f] endingColor:[NSColor colorWithCalibratedWhite:0.7f alpha:1.0f]];
//    onGradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedWhite:0.95 alpha:1.0f] endingColor:[NSColor colorWithCalibratedWhite:1.0f alpha:1.0f]];
    onGradient = [[NSGradient alloc] initWithStartingColor:[NSColor clearColor] endingColor:[NSColor clearColor]];
    onGradientPressed = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedWhite:0.45 alpha:1.0f] endingColor:[NSColor colorWithCalibratedWhite:0.55f alpha:1.0f]];
    offBorderColor = [NSColor colorWithCalibratedWhite:0.7f alpha:1.0f];
    onBorderColor = [NSColor colorWithCalibratedWhite:0.3f alpha:1.0f];
    checkColor = [NSColor colorWithCalibratedWhite:0.2f alpha:1.0f];
    dropShadow = [[NSShadow alloc] initWithColor:[NSColor colorWithCalibratedWhite:.863 alpha:.75] offset:NSMakeSize(0, 1.0) blurRadius:1.0];
    innerShadow1 = [[NSShadow alloc] init];
    [innerShadow1 setShadowColor:[NSColor colorWithCalibratedWhite:0.7f alpha:0.4f]];
    [innerShadow1 setShadowOffset:NSZeroSize];
    innerShadow2 = [[NSShadow alloc] init];
    [innerShadow2 setShadowColor:[NSColor colorWithCalibratedWhite:0.3 alpha:.6]];
}

- (id)initImageCell:(NSImage *)anImage {
    if (!(self = [super initImageCell:nil]))
        return nil;
    
    [self initializeCell_];
    return self;
}

-(id)initWithCoder:(NSCoder *)coder {
    if (!(self = [super initWithCoder:coder]))
        return nil;
    
    [self initializeCell_];
    return self;
}

-(void)initializeCell_ {
    [self cacheCheckPath_];
    [self cacheCheckBox_];
    [self setButtonType:NSToggleButton];
    [self setBezelStyle:NSRegularSquareBezelStyle];
}

-(void)cacheCheckPath_ {
    NSBezierPath *path = [NSBezierPath bezierPath];
    [path moveToPoint:NSMakePoint(13.0f, 58.0f)];
    [path lineToPoint:NSMakePoint(21.0f, 50.0f)];
    [path lineToPoint:NSMakePoint(40.0f, 70.0f)];
    [path curveToPoint:NSMakePoint(97.0f, 13.0f) controlPoint1:NSMakePoint(49.0f, 49.0f) controlPoint2:NSMakePoint(74.0f, 25.0f)];
    [path lineToPoint:NSMakePoint(97.0f, 17.0f)];
    [path curveToPoint:NSMakePoint(40.0f, 83.0f) controlPoint1:NSMakePoint(78.0f, 29.0f) controlPoint2:NSMakePoint(53.0f, 53.0f)];
    [path closePath];
    
    [self setCheckPath:path];
}

-(void)cacheCheckBox_ {
    [self setCheckBox:[NSBezierPath bezierPathWithRoundedRect:NSMakeRect(0.0f, 20.0f, 80.0f, 80.0f) xRadius:15.0f yRadius:15.0f]];
}

- (void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView {
    frame = NSInsetRect(frame, 2.0f, 2.0f);
    NSUInteger maxDimension = NSHeight(frame) > NSWidth(frame) ? NSHeight(frame) : NSWidth(frame);
    CGFloat scaleFactor = maxDimension / 100.0f;
    NSAffineTransform *scaleThenTranslateTransform = [NSAffineTransform transform];
    [scaleThenTranslateTransform scaleBy:scaleFactor];
//    CGFloat translateValue = [controlView isFlipped] ? -2.0f : 2.0f;
    NSAffineTransform *translateTransform = [NSAffineTransform transform];
    [translateTransform translateXBy:frame.origin.x yBy:frame.origin.y];

    NSBezierPath *checkBox = [[self checkBox] copy];
    [checkBox transformUsingAffineTransform:scaleThenTranslateTransform];
    [checkBox transformUsingAffineTransform:translateTransform];
    
    // Draw drop shadow
    if ([self isHighlighted] || [self state] == NSOffState) {
        [NSGraphicsContext saveGraphicsState];
        [dropShadow set];
        [checkBox fill];
        [NSGraphicsContext restoreGraphicsState];
    }
    
    // Draw gradient
    NSGradient *gradient = nil;
    if ([self isHighlighted])
        gradient = [self state] == NSOnState ? onGradientPressed : offGradientPressed;
    else
        gradient = [self state] == NSOnState ? onGradient : offGradient;
    [gradient drawInBezierPath:checkBox angle:-90.0f];
    
    // Stroke border
    NSColor *currentBorderColor = ([self state] == NSOnState) ? onBorderColor : offBorderColor;
    [currentBorderColor setStroke];
    [checkBox stroke];
    
    // Draw inner shadow
//    [innerShadow1 setShadowBlurRadius:(5.0f * scaleFactor)];
//    [checkBox fillWithInnerShadow:innerShadow1];
    [innerShadow2 setShadowOffset:NSMakeSize(0.0f, (-5.0f * scaleFactor))];
    [innerShadow2 setShadowBlurRadius:(15.0f * scaleFactor)];
    [checkBox fillWithInnerShadow:innerShadow2];
    
    if ([self state] == NSOffState)
        return;
    
    NSBezierPath *checkPath = [[self checkPath] copy];
    [checkPath transformUsingAffineTransform:scaleThenTranslateTransform];
    [checkPath transformUsingAffineTransform:translateTransform];
    [checkColor setFill];
    [checkPath fill];
}

- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)untilMouseUp {
    cellFrame = NSInsetRect(cellFrame, 2.0f, 2.0f);
    while ([theEvent type] != NSLeftMouseUp) {
        NSPoint eventPoint = [controlView convertPoint:[theEvent locationInWindow] fromView:nil];
        BOOL mouseInButton = [controlView mouse:eventPoint inRect:cellFrame];
        if (mouseInButton && ![self isHighlighted]) {
            [self setHighlighted:YES];
            [controlView setNeedsDisplayInRect:cellFrame];
        }
        if (!mouseInButton && [self isHighlighted]) {
            [self setHighlighted:NO];
            [controlView setNeedsDisplayInRect:cellFrame];
        }
        theEvent = [[controlView window] nextEventMatchingMask:(NSLeftMouseUpMask | NSLeftMouseDraggedMask)];
    }
    
    NSPoint finalPoint = [controlView convertPoint:[theEvent locationInWindow] fromView:nil];
    if ([controlView mouse:finalPoint inRect:cellFrame]) {
        [self setHighlighted:NO];
        [self setState:![self state]];
        NSDictionary *info = [(NSControl *)controlView infoForBinding:NSValueBinding];
        if (info) {
            id object = [info valueForKey:NSObservedObjectKey];
            NSString *keyPath = [info valueForKey:NSObservedKeyPathKey];
            NSInteger state = [self state];
            [object setValue:[NSNumber numberWithInteger:state] forKeyPath:keyPath];
        }
        [controlView setNeedsDisplayInRect:cellFrame];
    }
    return YES;
}

@end
